package org.softmed.rest.generation;

import java.io.File;
import java.util.List;

import org.softmed.rest.config.Application;
import org.softmed.rest.config.Module;
import org.softmed.rest.generation.refactoring.ApplicationService;
import org.softmed.rest.generation.refactoring.ModuleService;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.scafold.ModConfig;
import org.softmed.rest.generation.suites.HandlerSuiteManager;
import org.softmed.rest.generation.uri.ClassURIBuilder;

public class ServiceGenerationProcessor {

	ClassURIBuilder classURIBuilder = new ClassURIBuilder();

	public GenerationData buildApp(AppConfig app, String defaultXMLSuite)
			throws Throwable {

		if (app.getClasses() == null || app.getClasses().size() == 0) {
			throw new RuntimeException(
					"Application "
							+ app.getName()
							+ " has no registered classes. Can't generate REST service.");
			// return null;
		}

		Application application = new Application();
		application.setName(app.getName());
		application.setRelativeUri(app.getName());

		RESTModuleBuilder defaultBuilder = ModuleBuilderManager
				.getDefaultModuleBuilder();

		RESTModuleBuilder appBuilder = ModuleBuilderManager.getBuilder(app
				.getModuleBuilder());

		List<ModConfig> mods = app.getModules();

		ApplicationService applicationService = new ApplicationService();
		applicationService.setDirectoryName(new File(app.getPath()).getName());

		for (ModConfig mod : mods) {

			if (mod.getClasses() == null || mod.getClasses().size() == 0) {
				System.err
						.println("WARNING: Module "
								+ mod.getName()
								+ " of "
								+ "Application "
								+ app.getName()
								+ " has no registered classes. Can't generate module REST service.");
				continue;
			}

			String providerName = app.getPersistenceProvider();
			if (providerName == null)
				providerName = mod.getPersistenceProvider();

			if (providerName == null)
				throw new RuntimeException(
						"Application "
								+ app.getName()
								+ ", Module "
								+ mod.getName()
								+ ": "
								+ "No provider name specified. Can't generate REST service.");

			String xmlSuite = app.getXmlSuite();
			if (xmlSuite == null)
				xmlSuite = mod.getXmlSuite();
			if (xmlSuite == null)
				xmlSuite = defaultXMLSuite;

			if (xmlSuite == null)
				throw new RuntimeException(
						"Application "
								+ app.getName()
								+ ", Module "
								+ mod.getName()
								+ ": "
								+ "No XML Suite specified. Can't generate REST service.");

			String handlerSuite = app.getHandlerSuite();
			if (handlerSuite == null)
				handlerSuite = mod.getHandlerSuite();

			if (handlerSuite == null
					&& HandlerSuiteManager.getDefaultSuite() == null)
				throw new RuntimeException(
						"Application "
								+ app.getName()
								+ ", Module "
								+ mod.getName()
								+ ": "
								+ "No Handler Suite specified and no default handler suite registered. Can't generate REST service.");

			RESTModuleBuilder builder = null;
			RESTModuleBuilder modBuilder = null;
			if (mod.getModuleBuilder() != null)
				ModuleBuilderManager.getBuilder(mod.getModuleBuilder());

			if (modBuilder == null)
				builder = appBuilder;
			if (builder == null)
				builder = defaultBuilder;

			if (builder == null)
				throw new RuntimeException(
						"Application "
								+ app.getName()
								+ ", Module "
								+ mod.getName()
								+ ": "
								+ "No REST Module Builder specified. Can't generate REST service.");

			Module module = new Module();
			module.setName(mod.getName());
			module.setRelativeUri(mod.getName());

			classURIBuilder.buildModuleClassURIs(app, mod, application, module);

			ModuleService moduleService = builder.buildModule(app, mod,
					application, module, mod.getPath(), app
							.getGenerationConfig(), providerName, xmlSuite,
					handlerSuite);

			mod.setModuleService(moduleService);
			application.getModules().add(module);

			applicationService.getModules().add(moduleService);
		}

		GenerationData gd = new GenerationData();
		gd.setApplication(application);
		gd.setApplicationService(applicationService);

		return gd;
	}
}
